# Nushell Config File

module completions {
  # Custom completions for external commands (those outside of Nushell)
  # Each completions has two parts: the form of the external command, including its flags and parameters
  # and a helper command that knows how to complete values for those flags and parameters
  #
  # This is a simplified version of completions for git branches and git remotes
  def "nu-complete git branches" [] {
    ^git branch | lines | each { |line| $line | str replace '[\*\+] ' '' | str trim }
  }

  def "nu-complete git remotes" [] {
    ^git remote | lines | each { |line| $line | str trim }
  }

  export extern "git checkout" [
    branch?: string@"nu-complete git branches" # name of the branch to checkout
    -b: string                                 # create and checkout a new branch
    -B: string                                 # create/reset and checkout a branch
    -l                                         # create reflog for new branch
    --guess                                    # second guess 'git checkout <no-such-branch>' (default)
    --overlay                                  # use overlay mode (default)
    --quiet(-q)                                # suppress progress reporting
    --recurse-submodules: string               # control recursive updating of submodules
    --progress                                 # force progress reporting
    --merge(-m)                                # perform a 3-way merge with the new branch
    --conflict: string                         # conflict style (merge or diff3)
    --detach(-d)                               # detach HEAD at named commit
    --track(-t)                                # set upstream info for new branch
    --force(-f)                                # force checkout (throw away local modifications)
    --orphan: string                           # new unparented branch
    --overwrite-ignore                         # update ignored files (default)
    --ignore-other-worktrees                   # do not check if another worktree is holding the given ref
    --ours(-2)                                 # checkout our version for unmerged files
    --theirs(-3)                               # checkout their version for unmerged files
    --patch(-p)                                # select hunks interactively
    --ignore-skip-worktree-bits                # do not limit pathspecs to sparse entries only
    --pathspec-from-file: string               # read pathspec from file
  ]

  export extern "git push" [
    remote?: string@"nu-complete git remotes", # the name of the remote
    refspec?: string@"nu-complete git branches"# the branch / refspec
    --verbose(-v)                              # be more verbose
    --quiet(-q)                                # be more quiet
    --repo: string                             # repository
    --all                                      # push all refs
    --mirror                                   # mirror all refs
    --delete(-d)                               # delete refs
    --tags                                     # push tags (can't be used with --all or --mirror)
    --dry-run(-n)                              # dry run
    --porcelain                                # machine-readable output
    --force(-f)                                # force updates
    --force-with-lease: string                 # require old value of ref to be at this value
    --recurse-submodules: string               # control recursive pushing of submodules
    --thin                                     # use thin pack
    --receive-pack: string                     # receive pack program
    --exec: string                             # receive pack program
    --set-upstream(-u)                         # set upstream for git pull/status
    --progress                                 # force progress reporting
    --prune                                    # prune locally removed refs
    --no-verify                                # bypass pre-push hook
    --follow-tags                              # push missing but relevant tags
    --signed: string                           # GPG sign the push
    --atomic                                   # request atomic transaction on remote side
    --push-option(-o): string                  # option to transmit
    --ipv4(-4)                                 # use IPv4 addresses only
    --ipv6(-6)                                 # use IPv6 addresses only
  ]
}

# Get just the extern definitions without the custom completion commands
use completions *

# for more information on themes see
# https://www.nushell.sh/book/coloring_and_theming.html
let default_theme = {
    # color for nushell primitives
    separator: white
    leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off
    header: green_bold
    empty: blue
    bool: white
    int: white
    filesize: white
    duration: white
    date: white
    range: white
    float: white
    string: white
    nothing: white
    binary: white
    cellpath: white
    row_index: green_bold
    record: white
    list: white
    block: white
    hints: dark_gray

    # shapes are used to change the cli syntax highlighting
    shape_garbage: { fg: "#FFFFFF" bg: "#FF0000" attr: b}
    shape_binary: purple_bold
    shape_bool: light_cyan
    shape_int: purple_bold
    shape_float: purple_bold
    shape_range: yellow_bold
    shape_internalcall: cyan_bold
    shape_external: cyan
    shape_externalarg: green_bold
    shape_literal: blue
    shape_operator: yellow
    shape_signature: green_bold
    shape_string: green
    shape_string_interpolation: cyan_bold
    shape_datetime: cyan_bold
    shape_list: cyan_bold
    shape_table: blue_bold
    shape_record: cyan_bold
    shape_block: blue_bold
    shape_filepath: cyan
    shape_globpattern: cyan_bold
    shape_variable: purple
    shape_flag: blue_bold
    shape_custom: green
    shape_nothing: light_cyan
}

# The default config record. This is where much of your global configuration is setup.
let $config = {
  filesize_metric: false
  # basic, compact, compact_double, light, thin, with_love, rounded, reinforced, heavy, none, other
  table_mode: none
  use_ls_colors: true
  rm_always_trash: false
  color_config: $default_theme
  use_grid_icons: true
  footer_mode: "25" # always, never, number_of_rows, auto
  quick_completions: true  # set this to false to prevent auto-selecting completions when only one remains
  partial_completions: true  # set this to false to prevent partial filling of the prompt
  animate_prompt: false # redraw the prompt every second
  float_precision: 2
  use_ansi_coloring: true
  filesize_format: "auto" # b, kb, kib, mb, mib, gb, gib, tb, tib, pb, pib, eb, eib, zb, zib, auto
  edit_mode: emacs # emacs, vi
  max_history_size: 1000 # Session has to be reloaded for this to take effect
  sync_history_on_enter: true # Enable to share the history between multiple sessions, else you have to close the session to persist history to file
  menus: [
      # Configuration for default nushell menus
      # Note the lack of souce parameter
      {
        name: completion_menu
        only_buffer_difference: false
        marker: "| "
        type: {
            layout: columnar
            columns: 4
            col_width: 20   # Optional value. If missing all the screen width is used to calculate column width
            col_padding: 2
        }
        style: {
            text: green
            selected_text: green_reverse
            description_text: yellow
        }
      }
      {
        name: history_menu
        only_buffer_difference: true
        marker: "? "
        type: {
            layout: list
            page_size: 10
        }
        style: {
            text: green
            selected_text: green_reverse
            description_text: yellow
        }
      }
      {
        name: help_menu
        only_buffer_difference: true
        marker: "? "
        type: {
            layout: description
            columns: 4
            col_width: 20   # Optional value. If missing all the screen width is used to calculate column width
            col_padding: 2
            selection_rows: 4
            description_rows: 10
        }
        style: {
            text: green
            selected_text: green_reverse
            description_text: yellow
        }
      }
      # Example of extra menus created using a nushell source
      # Use the source field to create a list of records that populates
      # the menu
      {
        name: commands_menu
        only_buffer_difference: false
        marker: "# "
        type: {
            layout: columnar
            columns: 4
            col_width: 20
            col_padding: 2
        }
        style: {
            text: green
            selected_text: green_reverse
            description_text: yellow
        }
        source: { |buffer, position|
            $nu.scope.commands
            | where command =~ $buffer
            | each { |it| {value: $it.command description: $it.usage} }
        }
      }
      {
        name: vars_menu
        only_buffer_difference: true
        marker: "# "
        type: {
            layout: list
            page_size: 10
        }
        style: {
            text: green
            selected_text: green_reverse
            description_text: yellow
        }
        source: { |buffer, position|
            $nu.scope.vars
            | where name =~ $buffer
            | sort-by name
            | each { |it| {value: $it.name description: $it.type} }
        }
      }
      {
        name: commands_with_description
        only_buffer_difference: true
        marker: "# "
        type: {
            layout: description
            columns: 4
            col_width: 20
            col_padding: 2
            selection_rows: 4
            description_rows: 10
        }
        style: {
            text: green
            selected_text: green_reverse
            description_text: yellow
        }
        source: { |buffer, position|
            $nu.scope.commands
            | where command =~ $buffer
            | each { |it| {value: $it.command description: $it.usage} }
        }
      }
  ]
  keybindings: [
    {
        name: completion_menu
        modifier: none
        keycode: tab
        mode: emacs # Options: emacs vi_normal vi_insert
        event: {
            until: [
                { send: menu name: completion_menu }
                { send: menunext }
            ]
        }
    }
    {
        name: completion_previous
        modifier: shift
        keycode: backtab
        mode: [emacs, vi_normal, vi_insert] # Note: You can add the same keybinding to all modes by using a list
        event: { send: menuprevious }
    }
    {
        name: history_menu
        modifier: control
        keycode: char_x
        mode: emacs
        event: {
            until: [
                { send: menu name: history_menu }
                { send: menupagenext }
            ]
        }
    }
    {
      name: history_previous
      modifier: control
      keycode: char_z
      mode: emacs
      event: {
        until: [
            { send: menupageprevious }
            { edit: undo }
        ]
      }
    }
    # Keybindings used to trigger the user defined menus
    {
        name: commands_menu
        modifier: control
        keycode: char_t
        mode: [emacs, vi_normal, vi_insert]
        event: { send: menu name: commands_menu }
    }
    {
        name: vars_menu
        modifier: control
        keycode: char_y
        mode: [emacs, vi_normal, vi_insert]
        event: { send: menu name: vars_menu }
    }
    {
        name: commands_with_description
        modifier: control
        keycode: char_u
        mode: [emacs, vi_normal, vi_insert]
        event: { send: menu name: commands_with_description }
    }
  ]
}

# Do not overwrite open command on macOS
def nuopen [arg, --raw (-r)] {
    if $raw {
        open -r $arg
    } else {
        open $arg
    }
}

alias open = ^open

alias ll = ls -l
alias la = ls -a
alias lt = (ls | sort-by modified -r | sort-by type)
alias g = git
alias ga = git add
alias gaa = git add --all
alias gam = git am
alias gama = git am --abort
alias gamc = git am --continue
alias gams = git am --skip
alias gamscp = git am --show-current-patch
alias gap = git apply
alias gapa = git add --patch
alias gapt = git apply --3way
alias gau = git add --update
alias gav = git add --verbose
alias gb = git branch
alias gbD = git branch -D
alias gba = git branch -a
alias gbd = git branch -d
# alias gbda = git branch --no-color --merged | command grep -vE "^(\+|\*|\s*($(git_main_branch)|development|develop|devel|dev)\s*$)" | command xargs -n 1 git branch -d
alias gbl = git blame -b -w
alias gbnm = git branch --no-merged
alias gbr = git branch --remote
alias gbs = git bisect
alias gbsb = git bisect bad
alias gbsg = git bisect good
alias gbsr = git bisect reset
alias gbss = git bisect start
alias gc = git commit -v
alias gc! = git commit -v --amend
alias gca = git commit -v -a
alias gca! = git commit -v -a --amend
alias gcam = git commit -a -m
alias gcan! = git commit -v -a --no-edit --amend
alias gcans! = git commit -v -a -s --no-edit --amend
alias gcb = git checkout -b
alias gcd = git checkout develop
alias gcf = git config --list
alias gcl = git clone --recurse-submodules
alias gclean = git clean -id
alias gcm = git checkout $(git_main_branch)
alias gcmsg = git commit -m
alias gcn! = git commit -v --no-edit --amend
alias gco = git checkout
alias gcount = git shortlog -sn
alias gcp = git cherry-pick
alias gcpa = git cherry-pick --abort
alias gcpc = git cherry-pick --continue
alias gcs = git commit -S
alias gcsm = git commit -s -m
alias gd = git diff
alias gdca = git diff --cached
alias gdct = git describe --tags $(git rev-list --tags --max-count=1)
alias gdcw = git diff --cached --word-diff
alias gds = git diff --staged
alias gdt = git diff-tree --no-commit-id --name-only -r
alias gdw = git diff --word-diff
alias gf = git fetch
alias gfa = git fetch --all --prune
# alias gfg = git ls-files | grep
alias gfo = git fetch origin
alias gg = git gui citool
alias gga = git gui citool --amend
alias ggpull = git pull origin (git_current_branch)
alias ggpur = ggu
alias ggpush = git push origin (git_current_branch)
alias ggsup = git branch --set-upstream-to=origin/$(git_current_branch)
alias ghh = git help
alias gignore = git update-index --assume-unchanged
# alias gignored = git ls-files -v | grep "^[[:lower:]]"
alias git-svn-dcommit-push = git svn dcommit && git push github $(git_main_branch):svntrunk
alias gk = \gitk --all --branches
alias gke = \gitk --all $(git log -g --pretty=%h)
alias gl = git pull
alias glg = git log --stat
alias glgg = git log --graph
alias glgga = git log --graph --decorate --all
alias glgm = git log --graph --max-count=10
alias glgp = git log --stat -p
alias glo = git log --oneline --decorate
alias globurl = noglob urlglobber
alias glod = git log --graph --pretty=\%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\
alias glods = git log --graph --pretty=\%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset\ --date=short
alias glog = git log --oneline --decorate --graph
alias gloga = git log --oneline --decorate --graph --all
alias glol = git log --graph --pretty=\%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset\
alias glola = git log --graph --pretty=\%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset\ --all
alias glols = git log --graph --pretty=\%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset\ --stat
alias glp = _git_log_prettily
alias glum = git pull upstream $(git_main_branch)
alias gm = git merge
alias gma = git merge --abort
alias gmom = git merge origin/$(git_main_branch)
alias gmt = git mergetool --no-prompt
alias gmtvim = git mergetool --no-prompt --tool=vimdiff
alias gmum = git merge upstream/$(git_main_branch)
alias gp = git push
alias gpd = git push --dry-run
alias gpf = git push --force-with-lease
alias gpf! = git push --force
alias gpoat = git push origin --all && git push origin --tags
alias gpristine = git reset --hard && git clean -dffx
alias gpsup = git push --set-upstream origin $(git_current_branch)
alias gpu = git push upstream
alias gpv = git push -v
alias gr = git remote
alias gra = git remote add
alias grb = git rebase
alias grba = git rebase --abort
alias grbc = git rebase --continue
alias grbd = git rebase develop
alias grbi = git rebase -i
alias grbm = git rebase $(git_main_branch)
alias grbs = git rebase --skip
alias grep = grep --color=auto --exclude-dir={.bzr,CVS,.git,.hg,.svn,.idea,.tox}
alias grev = git revert
alias grh = git reset
alias grhh = git reset --hard
alias grm = git rm
alias grmc = git rm --cached
alias grmv = git remote rename
alias groh = git reset origin/$(git_current_branch) --hard
alias grrm = git remote remove
alias grs = git restore
alias grset = git remote set-url
alias grss = git restore --source
alias grt = cd "$(git rev-parse --show-toplevel || echo .)"
alias gru = git reset --
alias grup = git remote update
alias grv = git remote -v
alias gsb = git status -sb
alias gsd = git svn dcommit
alias gsh = git show
alias gsi = git submodule init
alias gsps = git show --pretty=short --show-signature
alias gsr = git svn rebase
alias gss = git status -s
alias gst = git status
alias gsta = git stash push
alias gstaa = git stash apply
alias gstall = git stash --all
alias gstc = git stash clear
alias gstd = git stash drop
alias gstl = git stash list
alias gstp = git stash pop
alias gsts = git stash show --text
alias gstu = git stash --include-untracked
alias gsu = git submodule update
alias gsw = git switch
alias gswc = git switch -c
# alias gtl = gtl(){ git tag --sort=-v:refname -n -l "${1}*" }; noglob gtl
alias gts = git tag -s
# alias gtv = git tag | sort -V
alias gunignore = git update-index --no-assume-unchanged
# alias gunwip = git log -n 1 | grep -q -c "\-\-wip\-\-" && git reset HEAD~1
alias gup = git pull --rebase
alias gupa = git pull --rebase --autostash
alias gupav = git pull --rebase --autostash -v
alias gupv = git pull --rebase -v
alias gwch = git whatchanged -p --abbrev-commit --pretty=medium
# alias gwip = git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign -m "--wip-- [skip ci]"

# def __git_prompt_git [...args] {
#     let GIT_OPTIONAL_LOCKS = 0; command git $args
# }

# def git_current_branch [] {
#     let ref = (__git_prompt_git symbolic-ref HEAD | split row "/")
#     let ret = $env.LAST_EXIT_CODE
#     if $ret != 0 {
#         if $ret == 128 {
#             ref = (__git_prompt_git rev-parse HEAD | split row "/")
#         }
#     }

#     let num = (echo $ref | length)
#     echo $ref | get ($num - 1)
# }

def nope [] {
    each { |it| $it == false }
}

def git_current_branch [] {
    let in-git-repo = (do --ignore-errors { git rev-parse --abbrev-ref HEAD } | empty? | nope)
    let status = (if $in-git-repo {
        git --no-optional-locks status --porcelain=2 --branch | lines
    } else {
        []
    })

    let on-named-branch = (if $in-git-repo {
      $status
      | where ($it | str starts-with '# branch.head')
      | first
      | str contains '(detached)'
      | nope
    } else {
      false
    })

    let branch-name = (if $on-named-branch {
        $status
        | where ($it | str starts-with '# branch.head')
        | split column ' ' col1 col2 branch
        | get branch
        | first
    } else {
        ''
    })

    $branch-name
}

def ggpush [] {
    git push origin (git_current_branch)
}


# Refer to bash version
# function git_current_branch() {
#     local ref
#     ref=$(__git_prompt_git symbolic-ref --quiet HEAD 2>/dev/null)
#     local ret=$?
#     if [[ $ret != 0 ]]; then
#         [[ $ret == 128 ]] && return # no git repo.
#         ref=$(__git_prompt_git rev-parse --short HEAD 2>/dev/null) || return
#     fi
#     echo ${ref#refs/heads/}
# }

